﻿using System;

namespace Moq
{
    /// <summary>
    /// Represents creating mock object.
    /// </summary>
    public static class XMock
    {
        /* TMock */

        /// <summary>
        /// Creates Mock object with the specified args.
        /// All get/set properties are set up.
        /// </summary>
        /// <typeparam name="TMock">The type of the mock.</typeparam>
        /// <param name="args">The args for constructor of the mock type.</param>
        /// <returns></returns>
        public static TMock Of<TMock>(params object[] args) where TMock : class
        {
            return Of<TMock>(true, args);
        }

        /// <summary>
        /// Creates Mock object with the specified args.
        /// </summary>
        /// <typeparam name="TMock">The type of the mock.</typeparam>
        /// <param name="setupAllProperties">if set to <c>true</c>, All get/set properties are set up.</param>
        /// <param name="args">The args for constructor of the mock type.</param>
        /// <returns></returns>
        public static TMock Of<TMock>(bool setupAllProperties, params object[] args) where TMock : class
        {
            return Of<TMock>(MockBehavior.Default, setupAllProperties, args);
        }

        private static TMock Of<TMock>(MockBehavior mockBehavior, bool setupAllProperties, object[] args) where TMock : class
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            var mock = new Mock<TMock>(mockBehavior, args) {CallBase = false};
            if (setupAllProperties)
            {
                mock.SetupAllProperties();
            }
            try
            {
                return mock.Object;
            }
            catch (ArgumentException exception)
            {
                throw new ArgumentException(exception.Message, exception);
            }
        }

        /// <summary>
        /// Creates strict Mock object with the specified args.
        /// </summary>
        /// <typeparam name="TMock">The type of the mock.</typeparam>
        /// <param name="args">The args for constructor of the mock type.</param>
        /// <returns></returns>
        public static TMock StrictOf<TMock>(params object[] args) where TMock : class
        {
            return Of<TMock>(MockBehavior.Strict, false, args);
        }
    }
}